package affichage;


import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collection;
 
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

import deroulementjeu.Partie;

import terrain.CaseTerrain;
import terrain.Coordonnees;
import terrain.Itineraire;
import terrain.Terrain;
import terrain.TypeTerrain;
import unite.CorpsACorps;
import unite.Distance;
import unite.Dresseur;
import unite.Obstacle;
import unite.Pokemon;
import unite.Potion;
import unite.TypeCarac;
import unite.TypeUnite;
import unite.Unite;
 

/**
 * Panel important qui affiche le terrain (il affiche toutes les instances
 * CaseTerrainView) pour afficher le type de terrain, le brouillard de guerre
 * ainsi que les unités qui se trouve sur le terrain.
 * Il est le moyen pour l'utilisateur d'interagir avec le jeu en cliquant sur
 * les différentes cases du terrain.
 * @author Alexis BRASY, Geoffrey LEQUESNE, Sandrine PIRIOU, Michel POPOV
 *
 */
public class TerrainView extends JPanel implements MouseListener {
	/** Valeur nécessaire pour la sérialisation */
    private static final long serialVersionUID = 1L;
    /** Le terrain que l'on affiche */
    private Terrain terrain;
    /** Tableau à deux dimensions contenant des CaseTerrainView */
    private ArrayList<ArrayList<CaseTerrainView>> terrainView;
    /** La fenêtre qui affiche la vue du terrain */
    private JFrame fenetre;
	/** Le panel MenuBas du jeu pour le que la vue du terrain change lorsque l'utilisateur
	 * interagit avec ce menu */
    private MenuBas menu2;
    /** Le panel MenuDroit de l'éditeur pour le que la vue du terrain change lorsque l'utilisateur
	 * interagit avec ce menu */
    private EditeurMenuDroit menu;
    /** La partie */
    private Partie partie;
    /** Le booléen si on est dans l'éditeur ou pas */
    private boolean editeurView = true;
    /** La liste des cases qui ne sont pas dans le brouillard de guerre */
    private ArrayList<CaseTerrain> casesAAfficher;
    /** L'unité sélectionnée actuellement par l'utilisateur */
    private Unite uniteSelected;
    /** Si l'unité sélectionnée actuellement par l'utilisateur est un pokémon*/
    private Pokemon pokemonSelected;
	/** Le booléen si l'utilisateur est dans un mode d'attaque à distance ou non */
    private boolean attDist;
	/** Si l'utilisateur a sélectionné une unité, c'est l'itinéraire de cette unité */
    private Itineraire itineraireUniteSelected;
    /** La collection qui contient les cases où l'unité sélectionnée peut se déplacer */
    private Collection<CaseTerrain> casesDeplacement;
    /** La collection qui contient les cases où l'unité sélectionnée peut attaquer à distance */
    private ArrayList<CaseTerrain> casesAttaqueADist;
    /** La liste des ennemis à afficher sur la carte (qui ne sont pas dans le brouillard) */
    private ArrayList<Unite> unitesEnnemiesAAfficher;
    
    
    /**
     * Constructeur du TerrainView (en fonction du terrain)
     * @param p la partie (qui contient le terrain)
     * @param fen la fenêtre où on affiche la vue
     * @param edit le booléen si on est dans l'éditeur ou pas
     */
    public TerrainView(Partie p, JFrame fen, boolean edit) {
        attDist = false;
        this.terrain = p.getTerrain();
        this.partie = p;
        this.editeurView = edit;
        terrainView = new ArrayList<ArrayList<CaseTerrainView>>();
        terrainView.ensureCapacity(terrain.getNbColonnes());
        for (int i = 0; i < terrain.getNbColonnes(); i++) {
            terrainView.add(i, new ArrayList<CaseTerrainView>());
            terrainView.get(i).ensureCapacity(terrain.getNbLignes());
            for (int j = 0; j < terrain.getNbLignes(); j++) {
                terrainView.get(i).add(j,
                        new CaseTerrainView(
                        terrain.getCase(new Coordonnees(i, j))));
            }
        }
        this.addMouseListener(this);
        this.fenetre = fen;
    }
    
    
    /**
     * Redéfinition de la méthode paintComponent pour qu'il dessine des hexagones
     * (grâce à la méthode drawPolygon)
     */
    @Override
    public void paintComponent(Graphics g) {
        CaseTerrainView ctv;
		
        this.setPreferredSize(
                new Dimension(
                        this.getTerrain().getNbColonnes()
                                * this.getCaseTerrainView().get(0).get(0).getHexaWidth()
                                        + this.getCaseTerrainView().get(0).get(0).getHexaWidth()
                                                / 2,
                                                this.getTerrain().getNbLignes()
                                                        * this.getCaseTerrainView().get(0).get(0).getHexaSide()
                                                                + this.getCaseTerrainView().get(0).get(0).getHexaHeight()
                                                                - this.getCaseTerrainView().get(0).get(0).getHexaSide()));
		
        uniteSelected = null;
		
        super.paintComponent(g);
        // On peint tout l'arrière-plan en blanc
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        Graphics2D g2d = (Graphics2D) g;

        for (int i = 0; i < this.terrain.getNbLignes(); i++) {
            for (int j = 0; j < this.terrain.getNbColonnes(); j++) {
        		
                // On parcourt toutes les cases terrain
                ctv = new CaseTerrainView(terrain.getCase(i, j));
                // On dessine l'hexagone terrain correspondant à cette case :
        		
                // Si on est dans l'éditeur on dessine la case
                if (editeurView == true) {
                    drawCaseTerrainView(g, ctv);
                } // Si on est pas dans l'éditeur
                else {
                    // On regarde si la case est visible
                    // Si elle est visible on l'affiche
                    if (casesAAfficher.contains(ctv.getCaseTerrain())) {
                        drawCaseTerrainView(g, ctv);
                        // Si une unité est sélectionnée
                        if (this.pokemonSelected != null) {
                            // Si on est en mode d'attaque à distance
                            if (attDist == true) {
            					
                                // On passe la transparence
                                g2d.setComposite(
                                        AlphaComposite.getInstance(
                                                AlphaComposite.SRC_OVER,
                                                3 * 0.1f));
                                if (this.casesAttaqueADist != null
                                        && this.casesAttaqueADist.contains(
                                                ctv.getCaseTerrain())) {
                                    Icon icon = new ImageIcon("img/rouge.gif");

                                    // On affiche l'image correspondante
                                    icon.paintIcon(this, g, ctv.getX(),
                                            ctv.getY());
                                }
                                // On remet l'opacité totale du composant
                                g2d.setComposite(
                                        AlphaComposite.getInstance(
                                                AlphaComposite.SRC_OVER, 1));
                            } // Sinon on affiche le déplacement
                            else {
                                g2d.setComposite(
                                        AlphaComposite.getInstance(
                                                AlphaComposite.SRC_OVER,
                                                3 * 0.1f));
                                // On affiche en rouge les cases où l'unité peut se déplacer	
                                if (this.casesDeplacement.contains(
                                        ctv.getCaseTerrain())
                                                || (this.casesAttaqueADist
                                                        != null
                                                                && this.casesAttaqueADist.contains(
                                                                        ctv.getCaseTerrain()))) {
                                    Icon icon = new ImageIcon("img/rouge.gif");

                                    // On affiche l'image correspondante
                                    icon.paintIcon(this, g, ctv.getX(),
                                            ctv.getY());
                                }
	            				
                                // et en bleu celle où elle va de déplacer
                                if (this.itineraireUniteSelected.getListeCases().contains(
                                        ctv.getCaseTerrain())) {
                                    Icon icon = new ImageIcon("img/bleu.gif");

                                    // On affiche l'image correspondante
                                    icon.paintIcon(this, g, ctv.getX(),
                                            ctv.getY());
                                }
                                g2d.setColor(Color.black);
                                // On remet l'opacité totale du composant
                                g2d.setComposite(
                                        AlphaComposite.getInstance(
                                                AlphaComposite.SRC_OVER, 1));
                            }
                        }
                    } // Sinon on l'affiche puis on redessine un polygone noir par dessus
                    else {
                        drawCaseTerrainView(g, ctv);
                        // On passe la transparence
                        g2d.setComposite(
                                AlphaComposite.getInstance(
                                        AlphaComposite.SRC_OVER, 3 * 0.1f));
                        // Si la case n'est pas VIDE, on affiche le brouillard
                        if (ctv.getCaseTerrain().getTypeTerrain()
                                != TypeTerrain.VIDE) {
                            Icon icon = new ImageIcon("img/noir.gif");

                            // On affiche l'image correspondante
                            icon.paintIcon(this, g, ctv.getX(), ctv.getY());
                        }
            			
                        // Si une unité est sélectionnée
                        if (this.pokemonSelected != null) {
            				
                            // On affiche en rouge les cases où l'unité peut se déplacer	
                            if (this.casesDeplacement.contains(
                                    ctv.getCaseTerrain())
                                            || (this.casesAttaqueADist != null
                                                    && this.casesAttaqueADist.contains(
                                                            ctv.getCaseTerrain()))) {
                                Icon icon = new ImageIcon("img/rouge.gif");

                                // On affiche l'image correspondante
                                icon.paintIcon(this, g, ctv.getX(), ctv.getY());
                            }
	            				
                            // et en bleu celle où elle va de déplacer
                            if (this.itineraireUniteSelected.getListeCases().contains(
                                    ctv.getCaseTerrain())) {
                                Icon icon = new ImageIcon("img/bleu.gif");

                                // On affiche l'image correspondante
                                icon.paintIcon(this, g, ctv.getX(), ctv.getY());
                            }
            				
                            g2d.setColor(Color.black);
                        }
            			
                        // On remet l'opacité totale du composant
                        g2d.setComposite(
                                AlphaComposite.getInstance(
                                        AlphaComposite.SRC_OVER, 1));
                    }
        			
                }
        		
                // On dessine l'unité se trouvant sur cette case (s'il y en a une) :
                // Si on est dans l'éditeur, on l'affiche
                if (editeurView == true) {
                    drawUnite(g, ctv);
                } // Si on est pas dans l'éditeur
                else {
                    // On regarde si la case est visible
                    // Si elle est visible on affiche l'unité dessus
                    if (casesAAfficher.contains(ctv.getCaseTerrain())) {
                        drawUnite(g, ctv);
                    }
                }
        		
            }
        }
    }
    
    
    /**
     * Affiche l'unité sur la CaseTerrainView ctv s'il y en a une en fonction de
     * son type
     * @param g
     * @param ctv
     */
    private void drawUnite(Graphics g, CaseTerrainView ctv) {
        if (ctv.getCaseTerrain().getUnite() != null) {
            g.setColor(ctv.getCaseTerrain().getUnite().getEquipe().getCouleur());
			
            if (!ctv.getCaseTerrain().getUnite().getEquipe().getCouleur().equals(
                    Color.black)) {
                g.fillOval(ctv.getX() + 5, ctv.getY() + ctv.getHexaHeight() - 40,
                        ctv.getHexaWidth() - 10, 20);
            }
			
            Icon icon = null;
            int niveau = ctv.getCaseTerrain().getUnite().getNiveau();

            switch (ctv.getCaseTerrain().getUnite().getType()) {
            case FEU: 
                if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/salameche_a.gif");
                } else if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_salameche_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/reptincel_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_reptincel_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/dracaufeu_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_dracaufeu_a.gif");
                }
                break;
			
            case PLANTE: 
                if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/bulbizarre_a.gif");
                } else if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_bulbizarre_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/herbizarre_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_herbizarre_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/florizarre_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_florizarre_a.gif");
                }
                break;
			
            case EAU:
                if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/carapuce_a.gif");
                } else if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_carapuce_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/carabaffe_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_carabaffe_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/tortank_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_tortank_a.gif");
                }
                break;
				
            case ELECTRIQUE: 
                if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/pichu_a.gif");
                } else if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_pichu_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/pikachu_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_pikachu_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/raichu_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_raichu_a.gif");
                }
                break;

            case VOL: 
                if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/roucool_a.gif");
                } else if (niveau == 0
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_roucool_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/roucoups_a.gif");
                } else if (niveau == 1
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_roucoups_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() != 0) {
                    icon = new ImageIcon("img/roucarnage_a.gif");
                } else if (niveau >= 2
                        && ctv.getCaseTerrain().getUnite().getDeplacement() == 0) {
                    icon = new ImageIcon("img/imm_roucarnage_a.gif");
                }
                break;

            case DRESSEUR:
                if (ctv.getCaseTerrain().getUnite().getEquipe().getNom().equals(
                        "Team1")) {
                    icon = new ImageIcon("img/dresseur_icon.gif");
                } else {
                    icon = new ImageIcon("img/dresseur2_icon.gif");
                }
                break;

            case OBSTACLE:
                icon = new ImageIcon("img/obstacle.gif");
                break;

            case POTION:
                icon = new ImageIcon("img/potion.png");
                break;

            case TELEPORTEUR:
                icon = new ImageIcon("img/warning.jpg");
                break;

            default:
                icon = new ImageIcon("img/warning.jpg");
                break;
            }
			
            icon.paintIcon(this, g,
                    ctv.getX() + ctv.getHexaWidth() / 2
                    - icon.getIconWidth() / 2,
                    ctv.getY() + ctv.getHexaHeight() / 2
                    - icon.getIconHeight() / 2);
			
            if (editeurView == false) {
                // Si on a un pokémon d'une équipe, on affiche sa barre de vie
                if (!ctv.getCaseTerrain().getUnite().getEquipe().getNom().equals(
                        "Team3")) {
                    g.setColor(Color.black);
					
                    g.fillRect(ctv.getX() + ctv.getHexaWidth() - 10,
                            ctv.getY() + 25, 7, ctv.getHexaHeight() - 2 * 25);
					
                    if (ctv.getCaseTerrain().getUnite().getPv()
                            > (50
                                    * this.getPartie().getRegle().getCaracUnite(
                                            ctv.getCaseTerrain().getUnite().getType(),
                                            TypeCarac.PV)
                                            / 100)) {
                        g.setColor(Color.green);
                    } else if (ctv.getCaseTerrain().getUnite().getPv()
                            > (25
                                    * this.getPartie().getRegle().getCaracUnite(
                                            ctv.getCaseTerrain().getUnite().getType(),
                                            TypeCarac.PV)
                                            / 100)) {
                        g.setColor(Color.orange);
                    } else {
                        g.setColor(Color.red);
                    }
                    int hauteurVie = (ctv.getCaseTerrain().getUnite().getPv()
                            * (ctv.getHexaHeight() - 2 * 25))
                                    / this.getPartie().getRegle().getCaracUnite(
                                            ctv.getCaseTerrain().getUnite().getType(),
                                            TypeCarac.PV);
	
                    int yHaut = ctv.getY() + ctv.getHexaHeight() - 25
                            - hauteurVie;
					
                    g.fillRect(ctv.getX() + ctv.getHexaWidth() - 10 + 1,
                            yHaut + 1, 7 - 2, hauteurVie - 2);
                }
            }
        }
		
    }

    /**
     * Affiche un polygone de la couleur en fonction du type terrain de la case
     * @param g le graphics
     * @param ctv la vue de la case terrain
     */
    public void drawCaseTerrainView(Graphics g, CaseTerrainView ctv) {
        Icon icon = null;
		
        // On définit l'image à afficher en fonction du TypeTerrain
        switch (ctv.getCaseTerrain().getTypeTerrain()) {
        case PLAINE:
            icon = new ImageIcon("img/plaine.gif");
            break;

        case SABLE:
            icon = new ImageIcon("img/sable.gif");
            break;

        case MER:
            icon = new ImageIcon("img/mer.gif");
            break;

        case MONTAGNE:
            icon = new ImageIcon("img/montagne.gif");
            break;

        case FORET:
            icon = new ImageIcon("img/foret.gif");
            break;

        case VIDE:
            icon = new ImageIcon("img/vide.gif");
            break;

        case GLACE:
            icon = new ImageIcon("img/glace.gif");
            break;

        default:
            icon = new ImageIcon("img/warning.jpg");
            break;
        }
        // On affiche l'image correspondante
        icon.paintIcon(this, g, ctv.getX(), ctv.getY());
        g.setColor(Color.black);
    }
    
    
	
    /**
     * Getter de la liste de cases d'attaque à distance
     * @return la liste
     */
    public ArrayList<CaseTerrain> getCasesAttDist() {
        return casesAttaqueADist;
    }

    /**
     * Setter de la liste de cases d'attaque à distance
     * @param casesAttaqueADist la liste
     */
    public void setCasesAttDist(ArrayList<CaseTerrain> casesAttaqueADist) {
        this.casesAttaqueADist = casesAttaqueADist;
    }
	
    /**
     * Setter de la fenêtre où on affiche la vue du terrain
     * @param fenetre la fenêtre JFrame
     */
    public void setFenetre(JFrame fenetre) {
        this.fenetre = fenetre;
    }

    /**
     * Getter de la liste d'unités ennemies à afficher
     * @return la liste
     */
    public ArrayList<Unite> getUnitesEnnemiesAAfficher() {
        return unitesEnnemiesAAfficher;
    }

    /**
     * Setter de la liste d'unités ennemies à afficher
     * @param unitesEnnemiesAAfficher la liste
     */
    public void setUnitesEnnemiesAAfficher(ArrayList<Unite> unitesEnnemiesAAfficher) {
        this.unitesEnnemiesAAfficher = unitesEnnemiesAAfficher;
    }

    /**
     * Getter de la fenêtre
     * @return la fenêtre JFrame
     */
    public JFrame getFenetre() {
        return this.fenetre;
    }

    /**
     * Getter du menu droit de l'éditeur
     * @return le menu
     */
    public EditeurMenuDroit getMenu() {
        return menu;
    }

    /**
     * Setter du menu droit de l'éditeur
     * @param menu le menu
     */
    public void setMenu(EditeurMenuDroit menu) {
        this.menu = menu;
    }
	
    /**
     * Getter du menu bas du jeu
     * @return le menu bas
     */
    public MenuBas getMenu2() {
        return menu2;
    }

    /**
     * Setter du menu bas du jeu
     * @param menu2 le menu
     */
    public void setMenu2(MenuBas menu2) {
        this.menu2 = menu2;
    }
	
    /**
     * Getter de la liste des cases pour le déplacement
     * @return la liste
     */
    public Collection<CaseTerrain> getCaseDeplacement() {
        return this.casesDeplacement;
    }
    
    /**
     * Getter du booléen si on est dans un mode d'attaque à distance
     * @return le booléen
     */
    public boolean isAttDist() {
        return attDist;
    }

    /**
     * Setter du booléen si on est dans un mode d'attaque à distance
     * @param attDist le booléen
     */
    public void setAttDist(boolean attDist) {
        this.attDist = attDist;
    }
    
    /**
     * Getter de l'unité sélectionnée
     * @return l'unité
     */
    public Unite getUniteSelected() {
        return uniteSelected;
    }

    /** 
     * Setter de l'unité sélectionnée
     * @param uniteSelected l'unité
     */
    public void setUniteSelected(Unite uniteSelected) {
        this.uniteSelected = uniteSelected;
    }

    /**
     * Getter du pokémon sélectionné
     * @return le pokémon
     */
    public Pokemon getPokemonSelected() {
        return pokemonSelected;
    }

    /**
     * Setter du pokémon sélectionné
     * @param pokemonSelected le pokémon
     */
    public void setPokemonSelected(Pokemon pokemonSelected) {
        this.pokemonSelected = pokemonSelected;
    }

    /**
     * Getter de la vue du terrain
     * @return le Terrain View
     */
    public ArrayList<ArrayList<CaseTerrainView>> getTerrainView() {
        return terrainView;
    }

    /**
     * Setter de la vue du terrain
     * @param terrainView la vue
     */
    public void setTerrainView(ArrayList<ArrayList<CaseTerrainView>> terrainView) {
        this.terrainView = terrainView;
    }
    
    /**
     * Getter du terrain
     * @return le terrain
     */
    public Terrain getTerrain() {
        return terrain;
    }
	
    /**
     * Getter de du la liste des vues de cases terrain
     * @return la liste
     */
    public ArrayList<ArrayList<CaseTerrainView>> getCaseTerrainView() {
        return terrainView;
    }

    /**
     * Setter du terrain
     * @param terrain le terrain
     */
    public void setTerrain(Terrain terrain) {
        this.terrain = terrain;
        this.redimTerrainView(terrain);
    }
    
    /**
     * Getter de la partie
     * @return la partie
     */
    public Partie getPartie() {
        return this.partie;
    }
	
    /**
     * Setter de la partie
     * @param p la partie
     */
    public void setPartie(Partie p) {
        this.partie = p;
    }
	
    /**
     * Getter de la liste de cases à afficher
     * @return la liste
     */
    public ArrayList<CaseTerrain> getCasesAAfficher() {
        return this.casesAAfficher;
    }
	
    /**
     * Setter de la liste de cases à afficher
     * @param caa la liste
     */
    public void setCasesAAfficher(ArrayList<CaseTerrain> caa) {
        this.casesAAfficher = caa;
    }
	
    /**
     * Setter de l'unité en cours
     * @param u l'unité en cours
     */
    public void setUniteEnCours(Unite u) {
        this.uniteSelected = u;
    }
	
    /**
     * Getter de l'itinéraire de l'unité en cours
     * @return l'itinéraire
     */
    public Itineraire getItineraireEnCours() {
        return this.itineraireUniteSelected;
    }
    

    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}
    
    @Override
    public void mouseReleased(MouseEvent e) {}

    /**
     * Redéfinition de la méthode mouseClicked
     */
    @Override
    public void mousePressed(MouseEvent e) {
        // Quand on presse un bouton de la souris
        int x = 0;
        int y = 0;
		
        boolean trouve = false;

        // On recherche les coordonnées du polygone où on a cliqué */
        for (int i = 0; i < this.terrain.getNbLignes() && !trouve; i++) {
            for (int j = 0; j < this.terrain.getNbColonnes() && !trouve; j++) {
                if (terrainView.get(i).get(j).getPolygone().contains(e.getX(),
                        e.getY())) {
                    x = i;
                    y = j;
                    trouve = true;
                    break;
                }
            }
        }
		
        // Si on est dans l'éditeur
        if (editeurView) {
            int team = 0;

            if (e.getButton() == 3
                    && this.terrain.getCase(new Coordonnees(x, y)).getUnite()
                            != null) {
                this.terrain.getCase(x, y).retirerUnite();
            }
			
            // On ajoute une unité
            if (e.getButton() == 1 && menu.getAjoutUnite().isSelected()) {
                if (this.terrain.getCase(x, y).getTypeTerrain()
                        != TypeTerrain.VIDE) {
                    if (menu.getEqu1().isSelected()
                            || menu.getEqu2().isSelected()) {
                        // On choisit l'équipe de l'unité à ajouter en fonction de la case
                        // "équipe" cochée par l'utilisateur
                        if (menu.getEqu1().isSelected()) {
                            team = 0;
                        } else if (menu.getEqu2().isSelected()) {
                            team = 1;
                        }
						
                        if (menu.getTypeUnite().equals(TypeUnite.ELECTRIQUE)
                                && (this.terrain.getCase(x, y).getTypeTerrain()
                                        != TypeTerrain.MER)) {
                            // S'il y a déjà une unité sur cette case, on la retire
                            if (this.terrain.getCase(x, y).getUnite() != null) {
                                this.terrain.getCase(x, y).retirerUnite();
                            }
                            new Distance(this.terrain.getCase(x, y),
                                    partie.getEquipe(team));
                        } else if (menu.getTypeUnite().equals(TypeUnite.DRESSEUR)
                                && (this.terrain.getCase(x, y).getTypeTerrain()
                                        != TypeTerrain.MER)) {
                            // S'il y a déjà une unité sur cette case, on la retire
                            if (this.terrain.getCase(x, y).getUnite() != null) {
                                this.terrain.getCase(x, y).retirerUnite();
                            }
                            new Dresseur(
                                    this.terrain.getCase(new Coordonnees(x, y)),
                                    partie.getEquipe(team));
                        } else {
                            if (this.terrain.getCase(x, y).getTypeTerrain()
                                    == TypeTerrain.MER) {
                                if ((menu.getTypeUnite() == TypeUnite.EAU)
                                        || (menu.getTypeUnite() == TypeUnite.VOL)) {
                                    // S'il y a déjà une unité sur cette case, on la retire
                                    if (this.terrain.getCase(x, y).getUnite()
                                            != null) {
                                        this.terrain.getCase(x, y).retirerUnite();
                                    }
                                    new CorpsACorps(
                                            this.terrain.getCase(
                                                    new Coordonnees(x, y)),
                                                    menu.getTypeUnite(),
                                                    partie.getEquipe(team));
                                }
                            } else {
                                // S'il y a déjà une unité sur cette case, on la retire
                                if (this.terrain.getCase(x, y).getUnite()
                                        != null) {
                                    this.terrain.getCase(x, y).retirerUnite();
                                }
                                new CorpsACorps(
                                        this.terrain.getCase(
                                                new Coordonnees(x, y)),
                                                menu.getTypeUnite(),
                                                partie.getEquipe(team));
                            }
                        }
                    } else if (menu.getEqu3().isSelected()) {
                        team = 2;

                        if (menu.getTypeUnite().equals(TypeUnite.POTION)) {
                            new Potion(
                                    this.terrain.getCase(new Coordonnees(x, y)),
                                    partie.getEquipe(team));
                        }

                        /*
                         else if(menu.getTypeUnite().equals(TypeUnite.TELEPORTEUR)) {
                         unit=new Teleporteur();
                         this.terrain.getCase(new Coordonnees(x,y)).ajouterUnite(unit);
                         }
                         */
                        if (menu.getTypeUnite().equals(TypeUnite.OBSTACLE)) {
                            new Obstacle(
                                    this.terrain.getCase(new Coordonnees(x, y)),
                                    partie.getEquipe(team));
                        }
                    }
                }
            } // On ajoute un terrain
            else if (e.getButton() == 1 && menu.getAjoutTerrain().isSelected()) {
                if (menu.getCase1x1().isSelected()) {
                    // Petit pinceau
                    if (this.terrain.getCase(x, y).getUnite() != null
                            && menu.getTypeTerrain() == TypeTerrain.VIDE) {
                        this.terrain.getCase(x, y).retirerUnite();
                    } else if (this.terrain.getCase(x, y).getUnite() != null
                            && menu.getTypeTerrain() == TypeTerrain.MER) {
                        if (this.terrain.getCase(x, y).getUnite().getType()
                                != TypeUnite.EAU
                                        && this.terrain.getCase(x, y).getUnite().getType()
                                                != TypeUnite.VOL
                                                && this.terrain.getCase(x, y).getUnite().getType()
                                                        != TypeUnite.POTION
                                                        && this.terrain.getCase(x, y).getUnite().getType()
                                                                != TypeUnite.OBSTACLE) {
                            this.terrain.getCase(x, y).retirerUnite();
                        }
                    }
                    this.terrain.getCase(new Coordonnees(x, y)).setTypeTerrain(
                            menu.getTypeTerrain());
                } else if (menu.getCase2x2().isSelected()) {
                    // Moyen pinceau
                    for (int i = x; (i <= x + 1)
                            && i < this.terrain.getNbLignes(); i++) {
                        for (int j = y; (j <= y + 1)
                                && j < this.terrain.getNbColonnes(); j++) {
                            if (this.terrain.getCase(i, j).getUnite() != null
                                    && menu.getTypeTerrain() == TypeTerrain.VIDE) {
                                this.terrain.getCase(i, j).retirerUnite();
                            } else if (this.terrain.getCase(i, j).getUnite()
                                    != null
                                            && menu.getTypeTerrain()
                                                    == TypeTerrain.MER) {
                                if (this.terrain.getCase(i, j).getUnite().getType()
                                        != TypeUnite.EAU
                                                && this.terrain.getCase(i, j).getUnite().getType()
                                                        != TypeUnite.VOL
                                                        && this.terrain.getCase(i, j).getUnite().getType()
                                                                != TypeUnite.POTION
                                                                && this.terrain.getCase(i, j).getUnite().getType()
                                                                        != TypeUnite.OBSTACLE) {
                                    this.terrain.getCase(i, j).retirerUnite();
                                }
                            }
                            this.terrain.getCase(i, j).setTypeTerrain(
                                    menu.getTypeTerrain());
                        }
                        if (x % 2 == 1) {
                            y++;
                        }
                    }
                } else if (menu.getCase4x4().isSelected()) {
                    // Grand pinceau
                    for (int i = x; (i <= x + 3)
                            && i < this.terrain.getNbLignes(); i++) {
                        for (int j = y; (j <= y + 3)
                                && j < this.terrain.getNbColonnes(); j++) {
                            if (this.terrain.getCase(i, j).getUnite() != null
                                    && menu.getTypeTerrain() == TypeTerrain.VIDE) {
                                this.terrain.getCase(i, j).retirerUnite();
                            } else if (this.terrain.getCase(i, j).getUnite()
                                    != null
                                            && menu.getTypeTerrain()
                                                    == TypeTerrain.MER) {
                                if (this.terrain.getCase(i, j).getUnite().getType()
                                        != TypeUnite.EAU
                                                && this.terrain.getCase(i, j).getUnite().getType()
                                                        != TypeUnite.VOL
                                                        && this.terrain.getCase(i, j).getUnite().getType()
                                                                != TypeUnite.POTION
                                                                && this.terrain.getCase(i, j).getUnite().getType()
                                                                        != TypeUnite.OBSTACLE) {
                                    this.terrain.getCase(i, j).retirerUnite();
                                }
                            }
                            this.terrain.getCase(new Coordonnees(i, j)).setTypeTerrain(
                                    menu.getTypeTerrain());
                        }
                        if (x % 2 == 1 && i % 2 == 1) {
                            y++;
                        } else if (x % 2 == 1 && i % 2 == 0) {
                            y--;
                        }
                    }
                }
            }
            fenetre.repaint();
        } // Si on est dans le jeu
        else {
            if (e.getButton() == 1
                    && this.terrain.getCase(new Coordonnees(x, y)).getUnite()
                            == null) {	
                attDist = false;
                this.casesAttaqueADist = null;
                this.uniteSelected = null;
                this.pokemonSelected = null;
                this.casesDeplacement = null;
                menu2.setSelection(0);
                menu2.suprimerMenu();
                menu2.afficherMenu();
				
                fenetre.setSize(fenetre.getWidth() + 1, fenetre.getHeight());
                fenetre.setSize(fenetre.getWidth() - 1, fenetre.getHeight());
            } else if (e.getButton() == 1
                    && this.terrain.getCase(new Coordonnees(x, y)).getUnite()
                            != null
                            && this.terrain.getCase(x, y).getTypeTerrain()
                                    != TypeTerrain.VIDE
                                    && this.getCasesAAfficher().contains(
                                            this.terrain.getCase(x, y))) {
                // Si on est en mode attaque à distance
                if (attDist == true) {
                    if (this.casesAttaqueADist != null
                            && this.casesAttaqueADist.contains(
                                    this.terrain.getCase(x, y))) {
                        // L'unité attaquante est l'unité seléctionée
                        Distance attaquant = (Distance) this.pokemonSelected;
                        // L'unité attaquée est celle qui se trouve sur la case où on a cliqué
                        Unite uniteAttaque = this.terrain.getCase(x, y).getUnite();
						
                        // On lance une attaque à distance !
                        attaquant.combatDistance(uniteAttaque);						
						
                        // On est plus dans le mode d'attaque à distance
                        attDist = false;
                        // L'unité vient d'attaquer, elle ne peut donc plus se déplacer
                        pokemonSelected.setDeplacement(0);
                        casesAttaqueADist = null;
                        menu2.getButtonAttDist().setEnabled(false);
                    } else {
                        attDist = false;
                        casesAttaqueADist = null;
                    }
                } // Sinon
                else {
                    menu2.repaint();
                    this.uniteSelected = this.terrain.getCase(new Coordonnees(x, y)).getUnite();
                    if (this.uniteSelected.getType() != TypeUnite.POTION
                            && this.uniteSelected.getType()
                                    != TypeUnite.OBSTACLE
                                    && this.uniteSelected.getType()
                                            != TypeUnite.TELEPORTEUR
                                            && this.uniteSelected.getType()
                                                    != TypeUnite.DRESSEUR
                                                    && this.uniteSelected.getEquipe()
                                                            == this.partie.getEquipeEnCours()) {
                        this.pokemonSelected = (Pokemon) uniteSelected;
                        this.itineraireUniteSelected = new Itineraire(
                                pokemonSelected);
                        this.casesDeplacement = this.itineraireUniteSelected.getListeCasesTerrainSelectionnables();
                    } else {
                        this.pokemonSelected = null;
                        if (this.itineraireUniteSelected != null) {
                            this.itineraireUniteSelected.reinitialiserCompletement();
                        }
                    }
					
                    menu2.setSelection(1);
                    menu2.setUnite(
                            this.terrain.getCase(new Coordonnees(x, y)).getUnite());
                    menu2.afficherMenu();
					
                    fenetre.setSize(fenetre.getWidth() + 1, fenetre.getHeight());
                    fenetre.setSize(fenetre.getWidth() - 1, fenetre.getHeight());
                }
            } else if (e.getButton() == 3 && this.pokemonSelected != null
                    && this.terrain.getCase(x, y).getTypeTerrain()
                    != TypeTerrain.VIDE) {
                attDist = false;
                CaseTerrain ctv = this.terrain.getCase(x, y);

                if (this.casesDeplacement.contains(ctv)) {
                    // 
                    this.itineraireUniteSelected.ajouterCase(x, y);
                    menu2.afficherMenu();
                    // paintImmediately(0,0,this.fenetre.getWidth(),this.fenetre.getHeight());
                    fenetre.setSize(fenetre.getWidth() + 1, fenetre.getHeight());
                    fenetre.setSize(fenetre.getWidth() - 1, fenetre.getHeight());
                    this.casesDeplacement = this.itineraireUniteSelected.getListeCasesTerrainSelectionnables();
                }
            }
				
        }
    }

    /**
     * Redimensionne la vue du terrain aux nouvelles coordonnées du terrain passé
     * en argument
     * @param t le terrain
     */
    public void redimTerrainView(Terrain t) {
        int oldI = terrainView.size();
        int oldJ = terrainView.get(0).size();
        int newI = t.getNbLignes();
        int newJ = t.getNbColonnes();
		
        // gestion de la nouvelle taille en I
        if (newI > terrainView.size()) {
            terrainView.ensureCapacity(newI);
            for (int i = oldI; i < newI; i++) {
                terrainView.add(i, new ArrayList<CaseTerrainView>());
                terrainView.get(i).ensureCapacity(newJ);
                for (int j = 0; j < newJ; j++) {
                    terrainView.get(i).add(j,
                            new CaseTerrainView(t.getCase(i, j)));
                }
            }
        } else if (newI < terrainView.size()) {
            while (newI < terrainView.size()) {
                terrainView.remove(terrainView.size() - 1);
            }
        }

        // gestion de la nouvelle taille en J
        for (int i = 0; i < newI; i++) {
            if (newJ > oldJ) {
                terrainView.get(i).ensureCapacity(newJ);
                for (int j = oldJ; j < newJ; j++) {
                    terrainView.get(i).add(j,
                            new CaseTerrainView(t.getCase(i, j)));
                }
            } else if (newJ < oldJ) {
                while (newJ < terrainView.get(i).size()) {
                    terrainView.get(i).remove((terrainView.get(i).size()) - 1);
                }
            }
        }
    }
	
	
}
